<template>
  <div ref="container" :class="className" :style="style"></div>
</template>

<script setup lang="ts" name="LaiCharts">
import { nextTick, onMounted, onUnmounted, ref, shallowRef, watch } from "vue";
import echarts from "./lib";
import { CanvasRenderer } from "echarts/renderers";
import type { EChartsOption } from "echarts";
import { getMaxWidth, getActualWidthOfChars, debounce } from "@/components/LaiEcharts/chartUtils";
echarts.use([CanvasRenderer]); //渲染模式
const props = withDefaults(
  defineProps<{
    option: EChartsOption;
    style?: { height: string; width: string };
    className?: string;
    containLabel?: boolean;
    onClick?: Function;
    legendClick?: Function;
  }>(),
  {
    option: () => ({}),
    style: () => ({
      height: "100%",
      width: "100%"
    }),
    className: "bar-chart",
    containLabel: false
  }
);
const container = ref<HTMLElement | null>(null); // 容器元素
const instance = shallowRef<echarts.ECharts | null>(null); // 实例

// 初始化
const initChart = () => {
  if (!container.value) return;
  //查看容器上是否已经挂载了echarts实例 , 如果已挂载就获取并使用该实例,如果未挂载就进行初始化
  instance.value = echarts.getInstanceByDom(container.value) || null;
  if (!instance.value) {
    instance.value = echarts.init(container.value);
  }
  drawChart();
  // 侦听图表事件
  addListeningChartEvent();
};
// 绘制图表
const drawChart = () => {
  // 如果props.option或instance.value不存在，则直接返回
  if (!props.option || !instance.value) return;
  // 是否开启自定义适应规则  目前只针对了type: bar、line 的图表 如果涉及到多y轴的情况请参考
  if (props.containLabel) {
    const { xAxis, grid, series }: any = props.option;
    let maxXAxisItem: (string | number)[] = [];
    if (Array.isArray(xAxis) && xAxis.length > 0 && xAxis) {
      let xAxisArr: (number | string)[] = [];
      xAxis.forEach(el => (xAxisArr = [...xAxisArr, ...el.data]));
      maxXAxisItem = [xAxisArr[0], xAxisArr[xAxisArr.length - 1]];
    } else if (xAxis) {
      maxXAxisItem = [xAxis!.data[0], xAxis!.data[xAxis!.data.length - 1]];
    }
    let leftXAxisWidth = getActualWidthOfChars(maxXAxisItem[0].toString()) || 0;
    let rightXAxisWidth = getActualWidthOfChars(maxXAxisItem[1].toString()) || 0;
    let maxYAxisArr: number[] = [];
    if (Array.isArray(series) && series.length > 0 && series) {
      series.forEach((el: any) => (maxYAxisArr = [...maxYAxisArr, ...el.data]));
    } else if (series) {
      maxYAxisArr = series.data;
    }
    let leftYAxisWidth = getMaxWidth([Math.min(...maxYAxisArr), Math.max(...maxYAxisArr)]);
    // 处理过后的option
    const newOption = {
      ...props.option,
      textStyle: {
        fontFamily: "Inter, system-ui, Avenir, Helvetica, Arial, sans-serif"
      },
      grid: {
        ...grid,
        containLabel: false,
        left: leftYAxisWidth > leftXAxisWidth / 2 ? leftYAxisWidth : leftXAxisWidth / 2,
        right: rightXAxisWidth / 2
      }
    };
    instance.value.setOption(newOption, {
      notMerge: true
    });
  } else {
    instance.value.setOption(props.option, {
      notMerge: true
    });
  }
};
// 图表自适应
const resize = debounce(() => {
  instance.value?.resize({
    animation: {
      duration: 200
    }
  });
}, 100);
// 重绘图表
watch(props, () => {
  nextTick(() => {
    drawChart();
  });
});
// echarts事件绑定
const addListeningChartEvent = () => {
  props.onClick &&
    instance.value?.on("click", e => {
      props.onClick!(e, instance.value, props.option);
    });
  props.legendClick &&
    instance.value?.on("legendselectchanged", e => {
      props.legendClick!(e, instance.value, props.option);
      console.log();
    });
};
onMounted(() => {
  nextTick(() => {
    initChart();
    if (container.value) {
      window.addEventListener("resize", resize);
    }
  });

  console.log(props.option);
});
onUnmounted(() => {
  instance.value?.dispose();
  window.removeEventListener("resize", resize);
});

// 定义要暴露给父组件的方法和属性
defineExpose({
  getInstance: () => instance.value,
  resize,
  drawChart
});
</script>
